import { getChatList, getChatHistory, getChatHistoryRecently, setChatUnread, deleteChatItem, sendFile, sendText } from '@/api/chat'
import short from 'short-uuid'
import { computeFileMd5 } from '@/utils'
// TODO: 再配置文件中
const limit = 20
const state = {
  chatList: [], // 对话列表
  chatHistory: {},
  historyOffset: {},
  requested: new Set(), // 已经请求过的聊天记录
  activedContactId: null
}

const mutations = {
  SET_CHAT_LIST: (state, data) => {
    state.chatList = data
  },
  UPDATE_CHAT_ITEM: (state, chatItem) => {
    const { contactId } = chatItem
    const i = state.chatList.findIndex(item => item.contactId === contactId)
    if (i !== -1) {
      const oldChatItem = state.chatList[i]
      const newChatItem = {
        ...oldChatItem,
        ...chatItem,
        unread: chatItem.unread ? oldChatItem.unread + chatItem.unread : 0// unread为0全部置为0，否则叠加
      }
      state.chatList.splice(i, 1, newChatItem)
      if (chatItem.latestTime !== oldChatItem.latestTime) {
        state.chatList.sort((a, b) => a.latestTime > b.latestTime ? -1 : 1)
      }
    }
  },
  DELETE_CHAT_ITEM: (state, i) => {
    state.chatList.splice(i, 1)
  },
  CREATE_CHAT_ITEM: (state, payload) => {
    state.chatList.unshift(payload)
    state.chatList.sort((a, b) => a.latestTime > b.latestTime ? -1 : 1)
  },
  SET_ACTIVED_CONTACT_ID: (state, data) => {
    state.activedContactId = data
  },
  SET_CHAT_HISTORY: (state, data) => {
    const { contactId, chatMsg } = data
    const msgList = Array.isArray(chatMsg) ? chatMsg : [chatMsg]
    state.chatHistory = {
      ...state.chatHistory,
      [contactId]: msgList
    }
  },
  INSERT_CHAT_MSG: (state, { contactId, chatMsg }) => {
    const msgList = Array.isArray(chatMsg) ? chatMsg : [chatMsg]
    if (!state.chatHistory[contactId]) {
      state.chatHistory = {
        ...state.chatHistory,
        [contactId]: msgList
      }
    } else {
      state.chatHistory[contactId].unshift(...msgList)
    }
  },
  APPEND_CHAT_MSG: (state, { contactId, chatMsg }) => {
    const msgList = Array.isArray(chatMsg) ? chatMsg : [chatMsg]
    if (!state.chatHistory[contactId]) {
      state.chatHistory = {
        ...state.chatHistory,
        [contactId]: msgList
      }
    } else {
      state.chatHistory[contactId].push(...msgList)
    }
  },
  UPDATE_CHAT_MSG: (state, { contactId, chatMsg }) => {
    const chatHistoryList = state.chatHistory[contactId]
    if (!Array.isArray(chatHistoryList)) {
      state.chatHistory = {
        ...state.chatHistory,
        [contactId]: [chatMsg]
      }
    } else {
      const { uuid } = chatMsg
      const idx = chatHistoryList.findIndex(item => item.uuid === uuid)
      if (idx !== -1) {
        chatHistoryList.splice(idx, 1, { ...chatHistoryList[idx], ...chatMsg })
      }
      console.log('update chat msg-----', chatMsg)
    }
  },
  ADD_REQUESTED: (state, contactId) => {
    state.requested.add(contactId)
  },
  INCREASE_HISTORY_OFFSET: (state, { contactId, amount }) => {
    if (!state.historyOffset[contactId]) {
      state.historyOffset[contactId] = amount
    } else {
      state.historyOffset[contactId] = state.historyOffset[contactId] + amount
    }
  }
}

const actions = {

  async initChatList({ commit }) {
    if (state.chatList.length > 0) return
    const { data } = await getChatList()
    commit('SET_CHAT_LIST', data)
  },

  async initChatHistory({ commit, state, dispatch }, contactId) {
    const hasInited = state.requested.has(contactId)
    if (state.chatHistory[contactId] && hasInited) return
    const { data } = await getChatHistoryRecently(contactId)
    let len = data.length
    if (len > 0) {
      commit('SET_CHAT_HISTORY', { contactId, chatMsg: data })
    } else {
      len = await dispatch('getChatHistory', contactId)
    }
    commit('ADD_REQUESTED', contactId)
    return len
  },
  async getChatHistory({ commit, state }, contactId) {
    const offset = state.historyOffset[contactId] || 0
    const { data } = await getChatHistory({ contactId, offset, limit })
    commit('INSERT_CHAT_MSG', { contactId, chatMsg: data })
    commit('INCREASE_HISTORY_OFFSET', { contactId, amount: data.length })
    return data.length
  },
  async setChatUnread({ commit }, { contactId, unread }) {
    commit('UPDATE_CHAT_ITEM', { contactId, unread })
    await setChatUnread({ contactId, unread })
  },
  // 生成发送的数据，并同步本地数据
  async genSendData({ commit, rootGetters, dispatch }, payload) {
    const date = (new Date()).toISOString()
    const sendChatMsg = {
      avatar: rootGetters.userInfo.avatar,
      createdAt: date,
      from: rootGetters.userInfo.id,
      uuid: short.generate(),
      ...payload
    }
    let localChatMsg = sendChatMsg
    if (['audio', 'image'].includes(sendChatMsg.type)) {
      localChatMsg = {
        ...sendChatMsg,
        url: (window.URL || window.webkitURL).createObjectURL(sendChatMsg.file)
      }
    }
    commit('APPEND_CHAT_MSG', {
      contactId: localChatMsg.to,
      chatMsg: localChatMsg
    })
    await dispatch('updateChatItem', { contactId: localChatMsg.to, chatMsg: localChatMsg })
    return sendChatMsg
  },
  // 更新对话列表项目
  async updateChatItem({ commit, dispatch }, { contactId, chatMsg }) {
    console.log('contactId--', contactId)
    const { type, content, createdAt, to, from } = chatMsg
    const latestMessageMap = {
      audio: '[语音]',
      image: '[图片]',
      file: '[文件]',
      text: content
    }
    const chatItem = {
      contactId,
      latestMessage: latestMessageMap[type],
      latestTime: createdAt,
      unread: state.activedContactId === to || state.activedContactId === from ? 0 : 1
    }
    const isNewChat = state.chatList.findIndex(item => item.contactId === contactId) === -1
    console.log('isNewChat----', isNewChat)
    if (isNewChat) {
      const { avatar, name, online } = await dispatch('contact/getContactInfo', contactId, { root: true })
      chatItem.avatar = avatar
      chatItem.name = name
      chatItem.online = online
      commit('CREATE_CHAT_ITEM', chatItem)
    } else {
      commit('UPDATE_CHAT_ITEM', chatItem)
    }
    return chatItem
  },
  // 接收到文字信息
  async socket_text({ commit, dispatch }, chatMsg) {
    commit('APPEND_CHAT_MSG', { contactId: chatMsg.from, chatMsg })
    await dispatch('updateChatItem', { contactId: chatMsg.from, chatMsg })
    return chatMsg
  },
  // 用户在线状态改变
  socket_onlineStatus({ commit }, payload) {
    console.log(`更新对话列表用户在线状态，用户:${payload.contactId}，${payload.status ? '离线' : '上线'}`)
    const { status, contactId } = payload
    commit('UPDATE_CHAT_ITEM', { contactId, online: status })
  },
  // 删除对话列表项目
  async deleteChatItem({ commit, state }, contactId) {
    if (!contactId) return
    const i = state.chatList.findIndex(item => item.contactId === contactId)
    if (i !== -1) {
      commit('DELETE_CHAT_ITEM', i)
      deleteChatItem(contactId)
    }
  },
  // 接收到语音信息
  async socket_audio({ commit, dispatch }, chatMsg) {
    console.log('接收到audio----', chatMsg)
    commit('APPEND_CHAT_MSG', { contactId: chatMsg.from, chatMsg })
    await dispatch('updateChatItem', { contactId: chatMsg.from, chatMsg: { ...chatMsg, content: '[语音]' }})
    return chatMsg
  },
  // 接收到图片信息
  async socket_image({ commit, dispatch }, chatMsg) {
    commit('APPEND_CHAT_MSG', { contactId: chatMsg.from, chatMsg })
    await dispatch('updateChatItem', { contactId: chatMsg.from, chatMsg: { ...chatMsg, content: '[图片]' }})
    return chatMsg
  },
  // 接收到文件
  async socket_file({ commit, dispatch }, chatMsg) {
    console.log('接受到文件-----', chatMsg)
    commit('APPEND_CHAT_MSG', { contactId: chatMsg.from, chatMsg })
    await dispatch('updateChatItem', { contactId: chatMsg.from, chatMsg: { ...chatMsg, content: '[图片]' }})
    return chatMsg
  },
  // 发送文件
  async sendFile({ dispatch, commit }, { file, to, type = 'file' }) {
    console.log('file----', file)
    const md5 = await computeFileMd5(file)
    console.log('md5---', md5)
    const chatMsg = await dispatch('genSendData', {
      to: to,
      fileName: file.name,
      size: file.size,
      type,
      loaded: 0,
      md5,
      file: file
    })
    console.log('genSendData---', chatMsg)
    // eslint-disable-next-line no-unused-vars
    const { content, loaded, ...sendForm } = chatMsg
    try {
      const { code } = await sendFile(sendForm, (e) => {
        // TODO: 这里需要节流
        console.log('上传事件----', e)
        const { loaded, total } = e
        const loadedPercent = Math.floor(loaded * 100 / total)
        commit('UPDATE_CHAT_MSG', {
          contactId: to,
          chatMsg: { uuid: chatMsg.uuid, loaded: loadedPercent }
        })
      })
      if (code !== 0) {
        // TODO: 文件发送异常处理
      }
    } catch (e) {
      // TODO: 文件发送异常处理
    }
  },

  // 发送文字
  async sendText() {

  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

